/* Copyright (C) 2010 Fredrique Samuels, fredriquesamuels@gmail.com */

/*
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "camera.h"

namespace tri
{

unsigned int TCamera::s_UIDCount = 0;
TCamera* TCamera::s_ActiveCamera = NULL;

TCamera::TCamera():m_ViewAngle(90),m_AspectRatio(1)
{
	mViewMode = TRI_PERSPECTIVE;
	mOrthoBounds = tri::TRectangle(-10,10,10,-10);
	s_UIDCount++;
	m_UID = s_UIDCount;
	this->m_LookAtPos.setValue(0,0,0);
}

TCamera::~TCamera()
{
}

unsigned int TCamera::getCamID(){
	return m_UID;
}

TVector TCamera::getPosition(){
	return m_Pos.getValue();
}

TVector TCamera::getRotation(){
	return m_Rot.getValue();
}
//
//void camera::setTargetPosition(vector* v,float t){
//	position.setTargetValue(v,t);
//}
//
//void camera::setTargetPosition(float x,float y,float z,float t){
//	position.setTargetValue(x,y,z,t);
//}
//
//void camera::setTargetRotation(vector* v,float t){
//	rotation.setTargetValue(v,t);
//}
//
//void camera::setTargetRotation(float x,float y,float z,float t){
//	rotation.setTargetValue(x,y,z,t);
//}
void TCamera::setPosition(TVector v){
	m_Pos = v;
}

void TCamera::setPosition(float x,float y,float z){
	m_Pos.setValue(x,y,z);
}

void TCamera::setRotation(TVector v){
	m_Rot = v;
}

void TCamera::setRotation(float x,float y,float z){
	m_Rot.setValue(x,y,z);
}
//
//void camera::setPosition(tri::vector v){
//	position.setValue(v);
//}
//
//void camera::setRotation(tri::vector v){
//	rotation.setValue(v);
//}
//
//void camera::setLookAt(vector* v){
//	this->look_at_pos.setValue(v);
//}

void TCamera::setLookAtVector(tri::TVector v){
	this->m_LookAtPos.setValue(v);
}

void TCamera::setTargetLookAtVector(tri::TVector v,float t){
	this->m_LookAtPos.setTargetValue(v.x,v.y,v.z,t);
}

void TCamera::action(){
	glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
	applyPerspective();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
	applyView();
	glGetFloatv(GL_MODELVIEW_MATRIX,m_ModelMatrix.elements);
	TCamera::s_ActiveCamera = this;
}

TCamera* TCamera::getActiveCamera(){
	return TCamera::s_ActiveCamera;
}

void TCamera::applyPerspective(){
	if(mViewMode==TRI_PERSPECTIVE){
		gluPerspective(this->m_ViewAngle,this->m_AspectRatio,0.1,100000);
	}else{
		glOrtho(mOrthoBounds.getLeft(),mOrthoBounds.getRight(),mOrthoBounds.getBottom(),mOrthoBounds.getTop(),0.1,100000);
	}
}

TMatrix TCamera::getModelMatrix() {
    return m_ModelMatrix;
}

//tri::vector camera::getAbsolutePosition(){
//	return tri::vector(model_view_matrix.elements[12],model_view_matrix.elements[13],model_view_matrix.elements[14]);
//}

//void camera::getInverseCameraRotationMatrix(tri::matrix* mat){
//	float mat3x3[9];
//	get_model_matrix(mat);
//	tri::matrix::get3x3MatrixFromMatrix(mat,mat3x3);
//	tri::matrix::invert(mat3x3);
//	tri::matrix::getMatrixFrom3x3Matrix(mat3x3,mat);
//}
//
//tri::vector camera::getGlobalPosition(tri::vector v){
//	tri::vector ret;
//	tri::matrix mat;
//	getInverseCameraRotationMatrix(&mat);
//	tri::matrix::mult_vmat(&mat,&v,&ret);
//	ret += getPosition();
//	ret.x = tri::utils::ABS(ret.x) < 0.001 ? 0 : ret.x;
//	ret.y = tri::utils::ABS(ret.y) < 0.001 ? 0 : ret.y;
//	ret.z = tri::utils::ABS(ret.z) < 0.001 ? 0 : ret.z;
//	return ret;
//}

void TCamera::applyView(){
	TVector r_LookAtPos = m_LookAtPos.getValue();
	gluLookAt(m_Pos.getValue().x,
			  m_Pos.getValue().y,
			  m_Pos.getValue().z,
			  r_LookAtPos.x,
  			  r_LookAtPos.y,
  			  r_LookAtPos.z,
			  0,1,0);
}

void TCamera::setViewAngle(float a){
	m_ViewAngle = a;
}

float TCamera::getViewAngle(){
	return m_ViewAngle;
}

void TCamera::setAspectRatio(float ar){
	m_AspectRatio = ar;
}

void TCamera::setViewMode(int mode){
	if (mode == TRI_PERSPECTIVE || mode == TRI_ORTHO){
		mViewMode = mode;
	}
}

void TCamera::setOrthoBounds(tri::TRectangle bounds){
	mOrthoBounds = bounds;
}

tri::TRectangle TCamera::getOrthoBounds(){
	return mOrthoBounds;
}


}
